home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / MSDOS / pcudp.c < prev    next >
C/C++ Source or Header  |  1979-12-31  |  21KB  |  873 lines

  1. /* --------------------------------- pcudp.c -------------------------------- */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* Handler for packet level exchanges (low level). It uses a packet driver
  8.  * as the communications medium at the UDP level. It uses ARP to locate
  9.  * the server and also responds to ARP requests.
  10.  *
  11.  * One MUST make sure that 'ip' is unique and 'sip' is correct.
  12.  * '+' options are mandatory!
  13.  *
  14.  *   int=    interrupt number (default is auto detect 0x60-0x80)
  15.  *  +sip=    server IP address
  16.  *   sport=    server UDP port (default is FLY8_SPORT which is usualy 0xf8f8)
  17.  *  +ip=    my IP address
  18.  *   port=    my UDP port (default is FLY8_PORT which is usualy 0xf8f9)
  19.  *
  20.  * When we receive a packet, it is put into ->data, then the logic determins
  21.  * where ->raw is.
  22.  *
  23.  * When we send a packet, the data is in ->raw and the protocol determins
  24.  * where the header starts.
  25. */
  26.  
  27. #include "fly.h"
  28. #include "pktdrvr.h"
  29.  
  30. #include <dos.h>
  31.  
  32.  
  33. /* chksum.asm */
  34. extern int    FAR chksum (Uchar *buf, int len);
  35.  
  36. #define MY_OFF(p)    (((Ushort far *)&(p))[0])
  37. #define MY_SEG(p)    (((Ushort far *)&(p))[1])
  38.  
  39. #define    FLY8_IP        0x0800U        /* ether type:  IP */
  40. #define    FLY8_ARP    0x0806U        /* ether type:  ARP */
  41. #define    FLY8_ARPQ    0x0001U        /* ARP op:      ARP Query */
  42. #define    FLY8_ARPR    0x0002U        /* ARP op:      ARP Reply */
  43. #define    FLY8_UDP    0x011U        /* IP protocol: UPD */
  44.  
  45. #define    FLY8_SPORT    0xf8f8U        /* server UDP port */
  46. #define    FLY8_PORT    0xf8f9U        /* my     UDP port */
  47.  
  48. #define MACADDRESS    6
  49.  
  50. #define ETHDEST        0        /* ethernet header */
  51. #define ETHSRCE        (ETHDEST   + MACADDRESS)
  52. #define ETHTYPE        (ETHSRCE   + MACADDRESS)
  53. #define ETHNNN        (ETHTYPE   + 2)
  54.  
  55. #define IPADDRESS    4
  56.  
  57. #define IPHVER        0        /* IP header */
  58. #define IPHTOS        (IPHVER    + 1)
  59. #define IPHLEN        (IPHTOS    + 1)
  60. #define IPHID        (IPHLEN    + 2)
  61. #define IPHFLAGS    (IPHID     + 2)
  62. #define IPHTTL        (IPHFLAGS  + 2)
  63. #define IPHPROTO    (IPHTTL    + 1)
  64. #define IPHCHECK    (IPHPROTO  + 1)
  65. #define IPHSRCE        (IPHCHECK  + 2)
  66. #define IPHDEST        (IPHSRCE   + IPADDRESS)
  67. #define IPHNNN        (IPHDEST   + IPADDRESS)
  68.  
  69. #define ARPHHTYPE    0        /* ARP header */
  70. #define ARPHPTYPE    (ARPHHTYPE + 2)
  71. #define ARPHHSIZE    (ARPHPTYPE + 2)
  72. #define ARPHPSIZE    (ARPHHSIZE + 1)
  73. #define ARPHOP        (ARPHPSIZE + 1)
  74. #define ARPHESRCE    (ARPHOP    + 2)
  75. #define ARPHISRCE    (ARPHESRCE + MACADDRESS)
  76. #define ARPHEDEST    (ARPHISRCE + IPADDRESS)
  77. #define ARPHIDEST    (ARPHEDEST + MACADDRESS)
  78. #define ARPHNNN        (ARPHIDEST + IPADDRESS)
  79.  
  80. #define UDPADDRESS    2
  81.  
  82. #define UDPXSRCE    0        /* UDP pseudo header */
  83. #define UDPXDEST    (UDPXSRCE  + IPADDRESS)
  84. #define UDPXZERO    (UDPXDEST  + IPADDRESS)
  85. #define UDPXPROTO    (UDPXZERO  + 1)
  86. #define UDPXLEN        (UDPXPROTO + 1)
  87. #define UDPXNNN        (UDPXLEN   + 2)
  88.  
  89. #define UDPHSRCE    0        /* UDP header */
  90. #define UDPHDEST    (UDPHSRCE  + UDPADDRESS)
  91. #define UDPHLEN        (UDPHDEST  + UDPADDRESS)
  92. #define UDPHCHECK    (UDPHLEN   + 2)
  93. #define UDPHNNN        (UDPHCHECK + 2)
  94.  
  95. #define APADDRESS    (IPADDRESS + UDPADDRESS)
  96.  
  97. #define APHDEST        0        /* Fly8 header */
  98. #define APHSRCE        (APHDEST   + APADDRESS)
  99. #define APHLEN        (APHSRCE   + APADDRESS)
  100. #define APHNNN        (APHLEN    + 2)
  101.  
  102. #define    PKSSIZE        1024        /* packet-driver stack size (words) */
  103.  
  104. typedef struct port    PORT;
  105. struct port {
  106.     int    flags;
  107. #define POF_ON        0x0001
  108.     void (interrupt far *pkint) (void);
  109.     int    iport;
  110.     struct NetDriver *driver;
  111.     short    netport;
  112.     int    intno;            /* packet-driver interrupt */
  113.     Uchar    mac[MACADDRESS];    /* my MAC address */
  114.     Uchar    ip[IPADDRESS];        /* my IP address */
  115.     Uchar    udport[UDPADDRESS];    /* my UDP port */
  116.     Uchar    addr[APADDRESS];    /* my Fly8 address */
  117.     int    handle;            /* packet-driver handle */
  118.     PACKET    *pack;            /* packet being received */
  119.     PACKET    *head;            /* outgoing packets */
  120.     PACKET    *tail;
  121.     int    *stack;            /* packet-driver stack */
  122.     int    version;
  123.     int    class;
  124.     int    type;
  125.     int    number;
  126.     char    *name;
  127.     int    basic;
  128. };
  129.  
  130. static PORT    ports[] = {
  131.     {0, pkint0, 1},
  132.     {0, pkint1, 2},
  133.     {0, pkint2, 3},
  134.     {0, pkint3, 4}
  135. };
  136. #define    NDEV    (rangeof(ports))
  137.  
  138. static int    nports = 0;        /* number of active ports */
  139. static Uchar    ether_arp[2] =
  140.             {0x0ff & (FLY8_ARP>> 8), 0x0ff & FLY8_ARP};
  141. static Uchar    ether_ip [2] =
  142.             {0x0ff & (FLY8_IP >> 8), 0x0ff & FLY8_IP};
  143. static Uchar    arp_query[2] =
  144.             {0x0ff & (FLY8_ARPQ >> 8), 0x0ff & FLY8_ARPQ};
  145. static Uchar    arp_reply[2] =
  146.             {0x0ff & (FLY8_ARPR >> 8), 0x0ff & FLY8_ARPR};
  147. static Uint    identification = 0;
  148.  
  149. static int    have_svr = 0;
  150. static Ulong    next_query = 0;
  151. static Uchar    svr_mac[MACADDRESS];
  152. static Uchar    svr_ip[IPADDRESS];
  153. static Uchar    svr_udport[UDPADDRESS];
  154. static Uchar    svr_addr[APADDRESS];
  155.  
  156.  
  157. LOCAL_FUNC void FAR    PuReceivePD (int dev, Ushort di, Ushort si,
  158.     Ushort bp, Ushort dx, Ushort cx, Ushort bx, Ushort ax, Ushort ds,
  159.     Ushort es);
  160. LOCAL_FUNC int NEAR    PuReceiveARP (PORT *port, PACKET *pack);
  161. LOCAL_FUNC int NEAR    PuReceiveIP  (PORT *port, PACKET *pack);
  162. LOCAL_FUNC int NEAR    PuReceiveETH (PORT *port, PACKET *pack);
  163. LOCAL_FUNC int NEAR    PuFindDriver (void);
  164. LOCAL_FUNC int NEAR    PuOptions (PORT *port, char *options);
  165. LOCAL_FUNC int FAR    PuInit (NETPORT *np, char *options);
  166. LOCAL_FUNC void FAR    PuTerm (NETPORT *np);
  167. LOCAL_FUNC int NEAR    PuSendETH (PORT *port, PACKET *p, Uchar *h, int len,
  168.     Uchar *ether_type);
  169. LOCAL_FUNC int NEAR    PuSendIP (PORT *port, PACKET *p, Uchar *h, int len,
  170.     int ip_type);
  171. LOCAL_FUNC int NEAR    PuSendUDP (PORT *port, PACKET *p, Uchar *h, int len);
  172. LOCAL_FUNC int NEAR    PuSendAP (PORT *port, PACKET *p, Uchar *h, int len);
  173. LOCAL_FUNC int NEAR    PuSendARPquery (PORT *port, PACKET *p, Uchar *h);
  174. LOCAL_FUNC int NEAR    PuSendARPreply (PORT *port, PACKET *p, Uchar *h,
  175.     Uchar *q);
  176. LOCAL_FUNC int FAR    PuSend (NETPORT *np, PACKET *p);
  177. LOCAL_FUNC int FAR    PuPoll (NETPORT *np);
  178.  
  179.  
  180. /* This function is called by the packet driver when a packet arrives. Each
  181.  * packet attracts two calls: in the first one (ax = 0) we get the packet size
  182.  * and should provide a buffer area in return. The second call (ax = 1) informs
  183.  * us that the packet was copied into the buffer.
  184.  *
  185.  * It is executed with interrupts off - don't do more than the absolute
  186.  * minimum in here.
  187. */
  188. LOCAL_FUNC void FAR
  189. PuReceivePD (int dev, Ushort di, Ushort si, Ushort bp, Ushort dx, Ushort cx,
  190.     Ushort bx, Ushort ax, Ushort ds, Ushort es)
  191. {
  192.     PORT    *port;
  193.     PACKET    *pack;
  194.     Uchar    *buff;
  195.  
  196.     st.flags1 |= SF_ASYNC;
  197.     switch (ax) {
  198.     case 0:                /* Space allocate call */
  199.         *&es = *&di = 0;
  200.         if (dev < 0 || dev >= NDEV ||
  201.             cx < ETHNNN || cx > (Ushort)PAKPACKLEN)
  202.             goto badret;
  203.         port = &ports[dev];
  204.         if (!(port->flags & POF_ON))
  205.             goto badret;
  206.         if (port->pack) {    /* stray packet? */
  207.             /* stats... */
  208.             packet_del (port->pack);
  209.             port->pack = 0;
  210.         }
  211.         if (F(pack = packet_new (cx, 0)))
  212.             goto badret;
  213.         port->pack = pack;
  214.         buff = pack->data;
  215.         *&es = MY_SEG (buff);
  216.         *&di = MY_OFF (buff);
  217.         break;
  218.     case 1:                /* Packet complete call */
  219.         if (dev < 0 || dev >= NDEV)
  220.             goto badret;
  221.         port = &ports[dev];
  222.         if (!(port->flags & POF_ON))
  223.             goto badret;
  224.         if (F(pack = port->pack))
  225.             goto badret;
  226.         port->pack = 0;
  227.         pack->netport = port->netport;
  228.  
  229.         if (PuReceiveETH (port, pack)) {
  230.             packet_del (pack);
  231.             goto badret;
  232.         }
  233.         break;
  234.     default:
  235. badret:
  236.         ++STATS_NETERRD;
  237.         break;
  238.     }
  239.     st.flags1 &= ~SF_ASYNC;
  240. }
  241.  
  242. /* Accept an ARP packet if it is for us and looks valid. Do not process it
  243.  * just yet - for speed we simply put in on a queue for later processing.
  244.  * We keep RARP too but they would be discarded later.
  245. */
  246. LOCAL_FUNC int NEAR
  247. PuReceiveARP (PORT *port, PACKET *pack)
  248. {
  249.     int    ret;
  250.     Uchar    *h;
  251.     int    len;
  252.  
  253.     ret = 1;
  254.     do {
  255.         len = pack->length;
  256.         if (len < ARPHNNN)
  257.             break;
  258.         h = pack->raw;
  259.  
  260. /* Note: we ignore broadcasts here.
  261. */
  262.         if (memcmp (h+ARPHIDEST, port->ip,  sizeof (port->ip)) &&
  263.             memcmp (h+ARPHEDEST, port->mac, sizeof (port->mac)))
  264.             break;
  265.         pack->next = NULL;
  266.         if (port->tail)
  267.             port->tail->next = pack;
  268.         else
  269.             port->head = pack;
  270.         port->tail = pack;
  271.         ret = 0;
  272.     } while (0);
  273.  
  274.     return (ret);
  275. }
  276.  
  277. #if 0
  278.  
  279. /* The following three functions are much clearer than the integrated one
  280.  * that replaces them. However, micro&soft vc1.5 dies horribly when inlining
  281.  * them.
  282. */
  283.  
  284. LOCAL_FUNC int NEAR    PuReceiveAP  (PORT *port, PACKET *pack);
  285. LOCAL_FUNC int NEAR    PuReceiveUDP (PORT *port, PACKET *pack);
  286. LOCAL_FUNC int NEAR    PuReceiveIP  (PORT *port, PACKET *pack);
  287.  
  288. /* Accept a Fly8 APplication packet.
  289. */
  290. LOCAL_FUNC int NEAR
  291. PuReceiveAP (PORT *port, PACKET *pack)
  292. {
  293.     int    ret;
  294.     Uchar    *h;
  295.     int    len;
  296.     int    n;
  297.  
  298.     ret = 1;
  299.     do {
  300.         len = pack->length;
  301.         if (len < APHNNN)
  302.             break;
  303.         h = pack->raw;
  304.         n = ComGBw (h+APHLEN);
  305.  
  306. /* Some systems round the size up so we cannot check for exact match.
  307. */
  308.         if (n < 3 || n > len)
  309.             break;
  310.         pack->address = h+APHSRCE;
  311.         pack->raw += APHNNN;
  312.         pack->length = (short)n;
  313.         packet_deliver (pack);
  314.         ret = 0;    /* packet always deleted */
  315.     } while (0);
  316.  
  317.     return (ret);
  318. }
  319.  
  320. /* Accept a UDP packet.
  321. */
  322. LOCAL_FUNC int NEAR
  323. PuReceiveUDP (PORT *port, PACKET *pack)
  324. {
  325.     int    ret;
  326.     Uchar    *h;
  327.     int    len;
  328.  
  329.     ret = 1;
  330.     do {
  331.         len = pack->length;
  332.         if (len < UDPHNNN)
  333.             break;
  334.         h = pack->raw;
  335.         if (memcmp (h+UDPHSRCE, svr_udport,   sizeof (svr_udport)) ||
  336.             memcmp (h+UDPHDEST, port->udport, sizeof (port->udport)))
  337.             break;
  338.         pack->raw    += UDPHNNN;
  339.         pack->length -= UDPHNNN;
  340.         ret = PuReceiveAP (port, pack);
  341.     } while (0);
  342.  
  343.     return (ret);
  344. }
  345.  
  346. /* Accept an IP packet.
  347. */
  348. LOCAL_FUNC int NEAR
  349. PuReceiveIP (PORT *port, PACKET *pack)
  350. {
  351.     int    ret;
  352.     Uchar    *h;
  353.     int    len;
  354.  
  355.     ret = 1;
  356.     do {
  357.         if (!have_svr)
  358.             break;
  359.  
  360.         len = pack->length;
  361.         if (len < IPHNNN)
  362.             break;
  363.         h = pack->raw;
  364.         if (FLY8_UDP != h[IPHPROTO])
  365.             break;
  366.         if (memcmp (h+IPHSRCE,  svr_ip,       sizeof (svr_ip)) ||
  367.             memcmp (h+IPHDEST,  port->ip,     sizeof (port->ip)))
  368.             break;
  369.         pack->raw    += IPHNNN;
  370.         pack->length -= IPHNNN;
  371.         ret = PuReceiveUDP (port, pack);
  372.     } while (0);
  373.  
  374.     return (ret);
  375. }
  376.  
  377. #else
  378.  
  379. /* Accept an IP packet.
  380. */
  381. LOCAL_FUNC int NEAR
  382. PuReceiveIP (PORT *port, PACKET *pack)
  383. {
  384.     int    ret;
  385.     int    n;
  386.     Uchar    *h;
  387.     int    len;
  388.  
  389.     ret = 1;
  390.     do {
  391.         if (!have_svr)
  392.             break;
  393.  
  394. /* Accept an IP packet.
  395. */
  396.         len = pack->length;
  397.         if (len < IPHNNN)
  398.             break;
  399.         h   = pack->raw;
  400.         if (FLY8_UDP != h[IPHPROTO])
  401.             break;
  402.         if (memcmp (h+IPHSRCE,  svr_ip,       sizeof (svr_ip)) ||
  403.             memcmp (h+IPHDEST,  port->ip,     sizeof (port->ip)))
  404.             break;
  405.         h   += IPHNNN;
  406.         len -= IPHNNN;
  407.  
  408. /* Accept a UDP packet.
  409. */
  410.         if (len < UDPHNNN)
  411.             break;
  412.         if (memcmp (h+UDPHSRCE, svr_udport,   sizeof (svr_udport)) ||
  413.             memcmp (h+UDPHDEST, port->udport, sizeof (port->udport)))
  414.             break;
  415.         h   += UDPHNNN;
  416.         len -= UDPHNNN;
  417.  
  418. /* Accept a Fly8 APplication packet.
  419. */
  420.         if (len < APHNNN)
  421.             break;
  422.         n = ComGBw (h+APHLEN);
  423.  
  424. /* Some systems round the size up so we cannot check for exact match.
  425. */
  426.         if (n < 3 || n > len)
  427.             break;
  428.         pack->raw     = h+APHNNN;
  429.         pack->length  = (short)n;
  430.         pack->address = h+APHSRCE;
  431.         packet_deliver (pack);
  432.         ret = 0;    /* packet always deleted */
  433.     } while (0);
  434.  
  435.     return (ret);
  436. }
  437.  
  438. #endif
  439.  
  440. /* Accept an incoming ethernet packet. It simply dispatches it to the
  441.  * proper handler based on the packet type.
  442. */
  443. LOCAL_FUNC int NEAR
  444. PuReceiveETH (PORT *port, PACKET *pack)
  445. {
  446.     Uchar    *h;
  447.  
  448.     h = pack->raw;
  449.     pack->raw    += ETHNNN;
  450.     pack->length -= ETHNNN;
  451.  
  452.     if (!memcmp (h+ETHTYPE, ether_arp, sizeof (ether_arp)))
  453.         return (PuReceiveARP (port, pack));
  454.     else if (!memcmp (h+ETHTYPE, ether_ip, sizeof (ether_ip)))
  455.         return (PuReceiveIP (port, pack));
  456.     else
  457.         return (1);
  458. }
  459.  
  460. /* Locate the interrupt for a packet driver.
  461. */
  462. LOCAL_FUNC int NEAR
  463. PuFindDriver (void)
  464. {
  465.     int    i;
  466.  
  467.     for (i = 0x060; i < 0x080; ++i)
  468.         if (test_for_pd (i))
  469.             return (i);
  470.     return (-1);
  471. }
  472.  
  473. /* Parse the options that this driver expects.
  474. */
  475. LOCAL_FUNC int NEAR
  476. PuOptions (PORT *port, char *options)
  477. {
  478.     long    l;
  479.  
  480.     if (get_narg (options, "int=", &l))
  481.         l = -1;
  482.     port->intno = (int)l;
  483.  
  484.     if (get_narg (options, "sip=", &l)) {
  485.         LogPrintf ("%s.%u: missing 'sip' option\n",
  486.             port->driver->name, port->iport);
  487.         return (1);
  488.     }
  489.     ComPBl (svr_ip, (Ulong)l);
  490.  
  491.     if (get_narg (options, "sport=", &l))
  492.         l = FLY8_SPORT;
  493.     ComPBw (svr_udport, (int)l);
  494.  
  495.     if (get_narg (options, "ip=", &l)) {
  496.         LogPrintf ("%s.%u: missing 'ip' option\n",
  497.             port->driver->name, port->iport);
  498.         return (1);
  499.     }
  500.     ComPBl (port->ip, (Ulong)l);
  501.  
  502.     if (get_narg (options, "port=", &l))
  503.         l = FLY8_PORT;
  504.     ComPBw (port->udport, (int)l);
  505.  
  506.     return (0);
  507. }
  508.  
  509. /* Called to initialize this driver.
  510. */
  511. LOCAL_FUNC int FAR
  512. PuInit (NETPORT *np, char *options)
  513. {
  514.     int    portno, rc;
  515.     PORT    *port;
  516.  
  517.     portno = np->unit-'1';
  518.     if (portno < 0 || portno >= NDEV) {
  519.         MsgEPrintf (-100, "%s.%c: bad port",
  520.             np->NetDriver->name, np->unit);
  521.         return (1);
  522.     }
  523.     port = &ports[portno];
  524.     if (port->flags & POF_ON) {
  525.         MsgEPrintf (-100, "%s.%c: already on",
  526.             np->NetDriver->name, np->unit);
  527.         return (1);
  528.     }
  529.  
  530.     port->driver = np->NetDriver;
  531.     port->netport = np->netport;
  532.     if (PuOptions (port, options))
  533.         return (1);
  534.  
  535.     if (-1 == port->intno)
  536.         port->intno = PuFindDriver ();
  537.     else if (!test_for_pd (port->intno))
  538.         port->intno = -1;
  539.     if (-1 == port->intno) {
  540.         MsgEPrintf (-100, "%s.%c: no driver",
  541.             np->NetDriver->name, np->unit);
  542.         return (1);
  543.     }
  544.     MsgPrintf (-100, "Intno 0x%x", port->intno);
  545.  
  546.     if (F(port->stack = (int *)memory_calloc (PKSSIZE,
  547.                         sizeof (*port->stack)))) {
  548.         MsgEPrintf (-100, "%s.%c: no mem",
  549.             np->NetDriver->name, np->unit);
  550.         return (1);
  551.     }
  552.  
  553.     pkinit (portno, PuReceivePD, &port->stack[PKSSIZE]);
  554.  
  555.     port->handle = access_type (port->intno, CL_ETHERNET, ANYTYPE, 0,
  556.         (char *)ether_arp, 0, port->pkint);
  557.     if (-1 == port->handle) {
  558.         MsgEPrintf (-100, "%s.%c: no handle",
  559.             np->NetDriver->name, np->unit);
  560.         port->stack = memory_cfree (port->stack, PKSSIZE,
  561.                         sizeof (*port->stack));
  562.         return (1);
  563.     }
  564.     if (driver_info (port->intno, port->handle, &port->version,
  565.             &port->class, &port->type, &port->number, &port->name,
  566.             &port->basic)) {
  567.         port->basic = 1;    /* what else ? */
  568.     }
  569.     MsgPrintf (-100, "Basic 0x%x", port->basic);
  570.  
  571.     port->pack = 0;
  572.     port->flags |= POF_ON;
  573.     ++nports;
  574.  
  575.     rc = get_address (port->intno, port->handle, (char *)port->mac,
  576.                         sizeof (port->mac));
  577.     if (rc) {
  578.         MsgPrintf (-100, "my MAC  failed %0x", Derr);
  579.         memset (port->mac, 0, sizeof (port->mac));
  580.     } else {
  581.         MsgWPrintf (-100, "my  MAC  %02x%02x%02x%02x%02x%02x",
  582.             port->mac[0], port->mac[1], port->mac[2],
  583.             port->mac[3], port->mac[4], port->mac[5]);
  584.         MsgWPrintf (-100, "my  IP   %u.%d.%d.%d",
  585.             port->ip[0], port->ip[1], port->ip[2], port->ip[3]);
  586.         MsgWPrintf (-100, "my  port %02x%02x",
  587.             port->udport[0], port->udport[1]);
  588.     }
  589.  
  590.     memcpy (svr_addr,           svr_ip,     IPADDRESS);
  591.     memcpy (svr_addr+IPADDRESS, svr_udport, UDPADDRESS);
  592.  
  593.     memcpy (port->addr,           port->ip,     IPADDRESS);
  594.     memcpy (port->addr+IPADDRESS, port->udport, UDPADDRESS);
  595.  
  596.     memset (svr_mac, 0xff, MACADDRESS);
  597.  
  598.     have_svr = 0;
  599.     next_query = st.present;    /* query immediately */
  600.  
  601.     return (0);
  602. }
  603.  
  604. /* Called to terminate this driver.
  605. */
  606. LOCAL_FUNC void FAR
  607. PuTerm (NETPORT *np)
  608. {
  609.     int    portno;
  610.     PORT    *port;
  611.  
  612.     portno = np->unit-'1';
  613.     if (portno < 0 || portno >= NDEV)
  614.         return;
  615.     port = &ports[portno];
  616.     if (!(port->flags & POF_ON))
  617.         return;
  618.     release_type (port->intno, port->handle);
  619.     if (port->pack) {
  620.         packet_del (port->pack);
  621.         port->pack = 0;
  622.     }
  623. /* delete outgoing packets !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
  624.     port->flags = 0;
  625.     port->stack = memory_cfree (port->stack, PKSSIZE,
  626.                         sizeof (*port->stack));
  627. }
  628.  
  629. /* Package an ethernet packet.
  630. */
  631. LOCAL_FUNC int NEAR
  632. PuSendETH (PORT *port, PACKET *p, Uchar *h, int len, Uchar *ether_type)
  633. {
  634.     len += ETHNNN;
  635.     h   -= ETHNNN;
  636.     memcpy (h+ETHDEST, svr_mac,    MACADDRESS);
  637.     memcpy (h+ETHSRCE, port->mac,  MACADDRESS);
  638.     memcpy (h+ETHTYPE, ether_type, 2);
  639.  
  640.     return (send_pkt (port->intno, (char *)h, len));
  641. }
  642.  
  643. /* Package an IP packet.
  644. */
  645. LOCAL_FUNC int NEAR
  646. PuSendIP (PORT *port, PACKET *p, Uchar *h, int len, int ip_type)
  647. {
  648.     len += IPHNNN;
  649.     h   -= IPHNNN;
  650.         h[IPHVER]   = (char)0x45;
  651.         h[IPHTOS]   = (char)0x10;    /* low delay */
  652.     ComPBw (h+IPHLEN,   (Uint)len);
  653.     ComPBw (h+IPHID,    identification++);
  654.     ComPBw (h+IPHFLAGS, 0x8000U);        /* don't fragment */
  655.         h[IPHTTL]   = (char)64;
  656.         h[IPHPROTO] = (char)ip_type;
  657.     memset (h+IPHCHECK, 0,            2);
  658.     memcpy (h+IPHSRCE,  port->ip,     IPADDRESS);
  659.     memcpy (h+IPHDEST,  svr_ip,       IPADDRESS);
  660.     ComPLw (h+IPHCHECK, (Uint)~chksum (h, IPHNNN/2));
  661.  
  662.     return (PuSendETH (port, p, h, len, ether_ip));
  663. }
  664.  
  665. /* Package a UDP packet.
  666. */
  667. LOCAL_FUNC int NEAR
  668. PuSendUDP (PORT *port, PACKET *p, Uchar *h, int len)
  669. {
  670.     int    chk;
  671.  
  672.     len += UDPHNNN;
  673.     h   -= UDPHNNN;
  674.     memcpy (h+UDPHSRCE,  port->udport, UDPADDRESS);
  675.     memcpy (h+UDPHDEST,  svr_udport,   UDPADDRESS);
  676.     ComPBw (h+UDPHLEN,   (Uint)len);
  677.     memset (h+UDPHCHECK, 0,            2);
  678.  
  679. /* We add a slack byte for even size, this is needed for the checksum.
  680.  * A packet is always a multiple of a large (power of 2) granularity
  681.  * factor so we always have room.
  682. */
  683.     if (len & 1)
  684.         h[len] = '\0';
  685.  
  686. /* Build a pseudo header sor the checksum.
  687. */
  688.     h -= UDPXNNN;
  689.     memcpy (h+UDPXSRCE,  port->ip,     IPADDRESS);
  690.     memcpy (h+UDPXDEST,  svr_ip,       IPADDRESS);
  691.         h[UDPXZERO]  = (char)0;
  692.         h[UDPXPROTO] = (char)FLY8_UDP;
  693.     ComPBw (h+UDPXLEN,   (Uint)len);
  694.     if (0 == (chk = ~chksum (h, (UDPXNNN+len+1)/2)))
  695.         chk = 0xffff;
  696.  
  697. /* Now store the checksum.
  698. */
  699.     h += UDPXNNN;
  700.     ComPLw (h+UDPHCHECK, (Uint)chk);
  701.  
  702.     return (PuSendIP (port, p, h, len, FLY8_UDP));
  703. }
  704.  
  705. /* Package a Fly8 application packet.
  706. */
  707. LOCAL_FUNC int NEAR
  708. PuSendAP (PORT *port, PACKET *p, Uchar *h, int len)
  709. {
  710.     h -= APHNNN;
  711.     if (p->address)
  712.         memcpy (h+APHDEST, p->address, APADDRESS);
  713.     else
  714.         memset (h+APHDEST, 0xff,       APADDRESS);
  715.     memcpy (h+APHSRCE, port->addr, APADDRESS);
  716.     ComPBw (h+APHLEN,  (Uint)len);
  717.     len += APHNNN;
  718.  
  719.     return (PuSendUDP (port, p, h, len));
  720. }
  721.  
  722. /* Send an ARP query. This is done repeatedly untill the server responds.
  723. */
  724. LOCAL_FUNC int NEAR
  725. PuSendARPquery (PORT *port, PACKET *p, Uchar *h)
  726. {
  727.     h -= ARPHNNN;
  728.     ComPBw (h+ARPHHTYPE,  1U);        /* hardware: ethernet */
  729.     ComPBw (h+ARPHPTYPE,  FLY8_IP);        /* protocol: IP */
  730.         h[ARPHHSIZE]= MACADDRESS;
  731.         h[ARPHPSIZE]= IPADDRESS;
  732.     memcpy (h+ARPHOP,     arp_query, sizeof (arp_query));
  733.     memcpy (h+ARPHESRCE,  port->mac, MACADDRESS);
  734.     memcpy (h+ARPHISRCE,  port->ip,  IPADDRESS);
  735.     memset (h+ARPHEDEST,  0,         MACADDRESS);
  736.     memcpy (h+ARPHIDEST,  svr_ip,    IPADDRESS);
  737.  
  738.     return (PuSendETH (port, p, h, ARPHNNN, ether_arp));
  739. }
  740.  
  741. /* Send an ARP reply. This is in respnse to a received query.
  742. */
  743. LOCAL_FUNC int NEAR
  744. PuSendARPreply (PORT *port, PACKET *p, Uchar *h, Uchar *q)
  745. {
  746.     h -= ARPHNNN;
  747.     memcpy (h+ARPHHTYPE, q+ARPHHTYPE, 2);
  748.     memcpy (h+ARPHPTYPE, q+ARPHPTYPE, 2);
  749.     memcpy (h+ARPHHSIZE, q+ARPHHSIZE, 1);
  750.     memcpy (h+ARPHPSIZE, q+ARPHPSIZE, 1);
  751.     memcpy (h+ARPHOP,    arp_reply,   sizeof (arp_reply));
  752.     memcpy (h+ARPHESRCE, port->mac,   MACADDRESS);
  753.     memcpy (h+ARPHISRCE, q+ARPHIDEST, IPADDRESS);
  754.     memcpy (h+ARPHEDEST, q+ARPHESRCE, MACADDRESS);
  755.     memcpy (h+ARPHIDEST, q+ARPHISRCE, IPADDRESS);
  756.  
  757.     return (PuSendETH (port, p, h, ARPHNNN, ether_arp));
  758. }
  759.  
  760. /* Send a packet. Directly called from the main program.
  761. */
  762. LOCAL_FUNC int FAR
  763. PuSend (NETPORT *np, PACKET *p)
  764. {
  765.     PORT    *port;
  766.     int    portno;
  767.     int    ret;
  768.  
  769.     ret = 1;
  770.     do {
  771.         if (!p) {
  772.             ret = 0;
  773.             break;
  774.         }
  775.         if (!have_svr)
  776.             break;
  777.         portno = np->unit-'1';
  778.         if (portno < 0 || portno >= NDEV)
  779.             break;
  780.         port = &ports[portno];
  781.         if (!(port->flags & POF_ON))
  782.             break;
  783.         ret = PuSendAP (port, p, p->raw, p->length);
  784.     } while (0);
  785.  
  786.     PuPoll (np);
  787.     return (ret);
  788. }
  789.  
  790. /* Do some housekeeping. This is necessary since we try to absolutely
  791.  * minimize the work done in the packet receiver routine.
  792. */
  793. LOCAL_FUNC int FAR
  794. PuPoll (NETPORT *np)
  795. {
  796.     PORT    *port;
  797.     PACKET    *p;
  798.     PACKET    *pack;
  799.     int    portno;
  800.     Ulong    flags;
  801.     int    ret;
  802.     Uchar    *h;
  803.  
  804.     portno = np->unit-'1';
  805.     if (portno < 0 || portno >= NDEV)
  806.         return (1);
  807.     port = &ports[portno];
  808.     if (!(port->flags & POF_ON))
  809.         return (1);
  810.  
  811. /* handle queued ARP packets.
  812. */
  813.     for (;;) {
  814.         flags = Sys->Disable ();
  815.         if (T(pack = port->head)) {
  816.             if (F(port->head = pack->next))
  817.                 port->tail = NULL;
  818.         }
  819.         Sys->Enable (flags);
  820.         if (!pack)
  821.             break;
  822.  
  823.         h = pack->raw;
  824.         if (!memcmp (h+ARPHOP, arp_reply, sizeof (arp_reply))) {
  825.             memcpy (svr_mac, h+ARPHESRCE, MACADDRESS);
  826.             have_svr = 1;
  827.             MsgWPrintf (-100, "svr MAC  %02x%02x%02x%02x%02x%02x",
  828.                 svr_mac[0], svr_mac[1], svr_mac[2],
  829.                 svr_mac[3], svr_mac[4], svr_mac[5]);
  830.             MsgWPrintf (-100, "svr IP   %u.%d.%d.%d",
  831.                 svr_ip[0], svr_ip[1], svr_ip[2], svr_ip[3]);
  832.             MsgWPrintf (-100, "svr port %02x%02x",
  833.                 svr_udport[0], svr_udport[1]);
  834.         } else if (!memcmp (h+ARPHOP, arp_query, sizeof (arp_query))) {
  835.             if (0 == (p = packet_new (0, -1))) {
  836.                 LogPrintf ("%s.%u: no packet\n",
  837.                     port->driver->name, port->iport);
  838.             } else {
  839.                 PuSendARPreply (port, p, p->raw, pack->raw);
  840.                 packet_del (p);
  841.             }
  842.         }
  843.         packet_del (pack);
  844.     }
  845.  
  846. /* send ARP query if needed.
  847. */
  848.     ret = 0;
  849.     if (!have_svr && st.present >= next_query) {
  850.         if (0 == (p = packet_new (0, -1))) {
  851.             LogPrintf ("%s.%u: no packet\n",
  852.                 port->driver->name, port->iport);
  853.             ret = 1;
  854.         } else {
  855.             ret = PuSendARPquery (port, p, p->raw);
  856.             packet_del (p);
  857.             next_query = st.present + 100;    /* 100ms wait */
  858.         }
  859.     }
  860.  
  861.     return (ret);
  862. }
  863.  
  864. struct NetDriver NEAR NetPcUDP = {
  865.     "PcUDP",
  866.     0,
  867.     NULL,    /* extra */
  868.     PuInit,
  869.     PuTerm,
  870.     PuSend,
  871.     PuPoll
  872. };
  873.